package com.hj.calendar.client;

import cn.hutool.core.util.ReUtil;
import com.github.caldav4j.methods.CalDAV4JMethodFactory;
import com.github.caldav4j.methods.HttpCalDAVReportMethod;
import com.github.caldav4j.methods.HttpPropFindMethod;
import com.github.caldav4j.model.request.CalendarData;
import com.github.caldav4j.model.request.CalendarQuery;
import com.github.caldav4j.model.request.CompFilter;
import com.github.caldav4j.model.request.TimeRange;
import com.hj.calendar.domain.constant.CaldavConfig;
import com.hj.calendar.domain.constant.SymbolConstant;
import com.hj.calendar.domain.dto.CaldavDdFsDTO;
import com.hj.calendar.domain.model.CaldavModel;
import lombok.extern.slf4j.Slf4j;
import net.fortuna.ical4j.model.DateTime;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.property.DavPropertyName;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hj
 * @Date 2022/5/22
 * @Description: 飞书caldav的相关操作
 */
@Slf4j
@Component
public class CaldavFsClient {


    /**
     * 获取获取日历的路径
     *
     * @param dto CaldavFsDTO
     * @return /用户名/UUID
     */
    public String getFsCalendarUrl(CaldavDdFsDTO dto) {
        HttpClient client = CaldavClient.createHttpClient(dto.getUsername(), dto.getPassword());
        CalDAV4JMethodFactory factory = CaldavClient.createFactory();
        DavPropertyNameSet props = new DavPropertyNameSet();
        props.add(DavPropertyName.DISPLAYNAME);
        props.add(DavPropertyName.GETETAG);
        // https://用户名:密码@caldav.feishu.cn/用户名
        String url = String.format("https://%s:%s@%s/%s", dto.getUsername(), dto.getPassword(), CaldavConfig.TWO_FS_HOST, dto.getUsername());
        try {
            HttpPropFindMethod propFindMethod = factory.createPropFindMethod(url, props, DavConstants.DEPTH_1);
            HttpHost hostConfig = new HttpHost(CaldavConfig.TWO_FS_HOST, CaldavConfig.PORT, CaldavConfig.PROTOCOL);
            HttpResponse response = client.execute(hostConfig, propFindMethod);
            log.info("\n\n返回207代表成功,返回的状态信息:{}\n\n", response.getStatusLine().toString());
            MultiStatusResponse[] responses = propFindMethod.getResponseBodyAsMultiStatus(response).getResponses();
            for (MultiStatusResponse r : responses) {
                String href = r.getHref();
                log.info("\n\n解析respond得到的getHref()路径:{}\n\n", href);
                // 正则匹配
                if (ReUtil.contains(SymbolConstant.UUID_REGEX, href)) {
                    log.info("\n路径包含32位的UUID:{}\n\n", href);
                    return href;
                }
            }
        } catch (IOException | DavException e) {
            e.printStackTrace();
            log.warn("\n获取飞书日历的路径报错:{}\n", e.getMessage());
        }
        return null;
    }

    /**
     * 获取飞书日历名称
     *
     * @param dto CaldavDdFsDTO
     * @return displayName
     */
    public String getFsDisplayName(CaldavDdFsDTO dto) {
        HttpClient client = CaldavClient.createHttpClient(dto.getUsername(), dto.getPassword());
        CalDAV4JMethodFactory factory = new CalDAV4JMethodFactory();
        try {
            //
            String url = String.format("https://%s:%s@%s%s", dto.getUsername(), dto.getPassword(),
                    CaldavConfig.TWO_FS_HOST, dto.getPathUuid());
            DavPropertyNameSet davPropertyNameSet = new DavPropertyNameSet();
            davPropertyNameSet.add(DavPropertyName.DISPLAYNAME);
            HttpPropFindMethod propFindMethod = factory.createPropFindMethod(url, davPropertyNameSet, DavConstants.DEPTH_0);
            HttpHost hostConfig = new HttpHost(CaldavConfig.TWO_FS_HOST, CaldavConfig.PORT, CaldavConfig.PROTOCOL);
            HttpResponse response = client.execute(hostConfig, propFindMethod);
            String status = response.getStatusLine().toString();
            if (status.contains(SymbolConstant.TWO_ZERO_SEVEN)) {
                // 日历名称
                String displayName = propFindMethod.getDisplayName(response, dto.getPathUuid());
                log.info(displayName);
                return displayName;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取飞书日程
     *
     * @param dto CaldavFsDTO
     */
    public List<CaldavModel> getCalendar(CaldavDdFsDTO dto) {
        // 处理查询日期时间
        CaldavClient.handleFsCaldavDate(dto);
        HttpClient client = CaldavClient.createHttpClient(dto.getUsername(), dto.getPassword());
        CalDAV4JMethodFactory factory = CaldavClient.createFactory();
        CalendarQuery calendarQuery = new CalendarQuery();
        try {
            CalendarData calendarData = new CalendarData(CalendarData.EXPAND,
                    new DateTime(dto.getCaldavStartTime()),
                    new DateTime(dto.getCaldavEndTime()), null);
            CompFilter compFilter = new CompFilter(net.fortuna.ical4j.model.Calendar.VCALENDAR);
            compFilter.addCompFilter(new CompFilter(net.fortuna.ical4j.model.Component.VEVENT));
            compFilter.getCompFilters().get(0)
                    .setTimeRange(
                            new TimeRange(
                                    new DateTime(dto.getCaldavStartTime()),
                                    new DateTime(dto.getCaldavEndTime())
                            )
                    );
            // 查询 过滤 条件
            calendarQuery.setCalendarDataProp(calendarData);
            calendarQuery.setCompFilter(compFilter);
            // 得到后面的路径
            String path = dto.getPathUuid();
            // https://用户名:密码@caldav.feishu.cn/用户名/uuid路径
            String url = String.format("https://%s:%s@%s%s", dto.getUsername(), dto.getPassword(), CaldavConfig.TWO_FS_HOST, path);
            HttpCalDAVReportMethod caldavReportMethod = factory.createCalDAVReportMethod(url, calendarQuery, DavConstants.DEPTH_0);
            HttpHost hostConfig = new HttpHost(CaldavConfig.TWO_FS_HOST, CaldavConfig.PORT, CaldavConfig.PROTOCOL);
            long a = System.currentTimeMillis();
            log.info("\n-----开始调用飞书日历:{}", a);
            HttpResponse response = client.execute(hostConfig, caldavReportMethod);
            long b = System.currentTimeMillis();
            log.info("\n----结束调用飞书日历:{},耗时:{}秒", b, (b - a) / 1000);
            String status = response.getStatusLine().toString();
            log.info("\n获取日历-返回207代表成功-返回的状态信息:{}\n", status);
            if (status.contains(SymbolConstant.TWO_ZERO_SEVEN)) {
                // calendar-data
                List<CaldavModel> fsCaldavModelList = new ArrayList<>();
                CaldavClient.handleCalendar(caldavReportMethod, response, fsCaldavModelList);
                return fsCaldavModelList;
            }
        } catch (ParseException | IOException | DavException e) {
            e.printStackTrace();
        }
        return null;
    }

}
